package fem2.material;

import inf.math.LinAlg;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import fem2.Element;
import fem2.MaterialModel;
import fem2.Model;

/**
 * TODO
 * 
 * @author hbui
 * 
 */
public abstract class TopOptFilter {

	protected Map<Element, ArrayList<Element>> mapElemId = new HashMap<Element, ArrayList<Element>>();
	protected Map<Element, ArrayList<Double>> mapElemWeight = new HashMap<Element, ArrayList<Double>>();

	/**
	 * 
	 * initialize filter
	 */
	public abstract void initialize();

	/**
	 * compute filtered compliance senstivity
	 * 
	 * @param e
	 * @param mm
	 * @return
	 */
	public abstract double filterComplianceSensitivity(Element e, MaterialModel mm);

	/**
	 * compute filtered volume senstivity
	 * 
	 * @param e
	 * @param mm
	 * @return
	 */
	public abstract double filterVolumeSensitivity(Element e, MaterialModel mm);

	/**
	 * compute filtered density
	 * 
	 * @param e
	 * @param mm
	 * @return
	 */
	public abstract double filterDensity(Element e, MaterialModel mm);

	protected void computeDistance(Model m, double rmin) {
		int ne = m.countElements();
		/*
		 * compute center of elements
		 */
		Map<Element, double[]> elemCenter = new HashMap<Element, double[]>();
		for (int i = 0; i < ne; i++) {
			Element e = m.getElement(i);
			double[] c = e.getMeshPart().computeCenter();
			elemCenter.put(e, c);
		}
		/*
		 * from each element, compute distance to other element and compare to
		 * rmin
		 */
		for (int i = 0; i < ne; i++) {
			Element e = m.getElement(i);
			double[] c = elemCenter.get(e);
			ArrayList<Element> elemList = new ArrayList<Element>();
			ArrayList<Double> elemDist = new ArrayList<Double>();
			for (int j = 0; j < ne; j++) {
				Element e1 = m.getElement(j);
				double[] c1 = elemCenter.get(e1);
				double d = LinAlg.diffNorm2(c.length, c, c1);
				if (d < rmin) {
					elemList.add(e1);
					elemDist.add(rmin - d);
				}
			}
			mapElemId.put(e, elemList);
			mapElemWeight.put(e, elemDist);
		}

		// Debugger.watch("compute distance completed");
	}
}
